import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { getUser } from '../kinde'
import { db } from '../db'
import {
  expenseInsertSchema,
  expenses as expensesTable
} from '../db/schema/expenses'
import { and, desc, eq, sum } from 'drizzle-orm'
import { createExpenseSchema } from '../sharedTypes'

export const expensesRoute = new Hono()
  .get('/', getUser, async c => {
    const user = c.var.user

    const expenses = await db
      .select()
      .from(expensesTable)
      .where(eq(expensesTable.userId, user.id))
      .orderBy(desc(expensesTable.createdAt))
      .limit(100)

    return c.json({ expenses })
  })
  .get('/:id{[0-9]+}', getUser, async c => {
    const id = Number(c.req.param('id'))
    const expense = await db
      .select()
      .from(expensesTable)
      .where(
        and(eq(expensesTable.userId, c.var.user.id), eq(expensesTable.id, id))
      )
      .then(res => res[0])

    if (!expense) {
      return c.notFound()
    }
    return c.json({ expense })
  })
  .get('/total-spent', getUser, async c => {
    const total = await db
      .select({ total: sum(expensesTable.amount) })
      .from(expensesTable)
      .where(eq(expensesTable.userId, c.var.user.id))
      .then(res => res[0]!.total)

    return c.json({ total })
  })
  .post('/', getUser, zValidator('json', createExpenseSchema), async c => {
    const expense = await c.req.valid('json')

    const validateExpense = expenseInsertSchema.parse({
      ...expense,
      userId: c.var.user.id
    })
    const res = await db
      .insert(expensesTable)
      .values(validateExpense)
      .returning()
      .then(res => res[0])

    return c.json(res)
  })
  .delete('/:id{[0-9]+}', getUser, async c => {
    const id = Number(c.req.param('id'))
    const res = await db
      .delete(expensesTable)
      .where(
        and(eq(expensesTable.userId, c.var.user.id), eq(expensesTable.id, id))
      )
      .returning()
      .then(res => res[0])

    if (!res) {
      return c.notFound()
    }
    return c.json(res)
  })
